#!/bin/bash
#========================================================================
# Author: YSLin
# Email: 
# File Name: string.sh
# Description: 
# 
#    str_special - 含控制文字的字串

#    str_complex - 巢狀的字串("", ''的差異)

#    str_compare - 比對字串

#    str_fieldsplit - 將字串分割成幾個單字
#    str_match_expr - 抽取出與正規表示一致的部分
#    str_multiline - 寫一個橫跨多行的字串替換

#    ${var:-str}     如果 var 變數存在且為非空值，就傳回其值 ﹔如果 var 變數存在但為空值或者 var 變數根本不存在，則傳回 str
#    ${var-str}      如果 var 變數存在且為非空值，就傳回其值 ﹔若 var 變數存在但為空值，則傳回空值 ﹔如果 var 變數不存在，則傳回 str。
#    ${var:=str}     如果 var 變數存在且為非空值，就傳回其值 ﹔如果 var 變數存在但為空值或者 var 變數根本不存在，就把 str 設定給 var ，並傳回 str。
#    ${var=str}      如果 var 變數存在且為非空值，就傳回其值 ﹔若 var 變數存在但為空值，則傳回空值 ﹔如果 var 變數不存在，就把 str 設定給 var ，並傳回 str
#    ${var:?info}    如果 var 變數存在且為非空值，就傳回其值 ﹔如果 var 變數存在但為空值或者 var 變數根本不存在，就會顯示 var: 及 info 的訊息
#    ${var?info}     如果 var 變數存在且為非空值，就傳回其值 ﹔若 var 變數存在但為空值，則傳回空值 ﹔如果 var 變數不存在，就會顯示 var: 及 info 的訊息。
#    ${var:+str}     如果 var 變數存在且為非空值，則傳回 str ﹔如果 var 變數存在但為空值或者 var 變數根本不存在，就傳回空值。
#    ${var+str}      如果 var 變數存在，且不論為空值或非空值，皆傳回 str ﹔如果 var 變數不存在，就傳回空值

#    str_wordsplit - 取出字串的任意單字

#    str_substr_bash.sh - 取出字串的一部分（bash）
#    str_substr.sh - 取出字串的一部分

#    ${var:number}   number 為一數字，若 var 的變數值含有 8 個字元，當 number 為 3 時，表示取得第三個字元以後的部分
#    ${var:n1:n2}    若 var 的變數值含有 8 個字元，當 n1 為 3，n2 為 6 時，表示取得第三個字元以後的六個字元。


#    str_length - 調查字串長度

#    ${#var}         傳回 var 變數值的字元數。
#

#    str_replace_bash - 取代字串（bash）
#    str_replace - 使用sed來取代字串

#    ${var#pattern}      把 pattern 與 var 變數值做比對時，是從 var 變數值的前面部分比對起，如果有符合之處，就刪除變數值中最短的部分，並傳回其餘的變數值
#    ${var##pattern}     把 pattern 與 var 變數值做比對時，是從 var 變數值的前面部分比對起，如果有符合之處，就刪除變數值中最長的部分，並傳回其餘的變數值
#	 ${var%pattern}      把 pattern 與 var 變數值做比對時，是從 var 變數值的後面部分比對起，如果有符合之處，就刪除變數值中最短的部分，並傳回其餘的變數值
#	 ${var%%pattern}     把 pattern 與 var 變數值做比對時，是從 var 變數值的後面部分比對起，如果有符合之處，就刪除變數值中最長的部分，並傳回其餘的變數值
#	 ${var/pat1/pat2}    若變數值中含有 pat1，就將第一個 pat1用 pat2 作替代
#    ${var//pat1/pat2}   若變數值中含有 pat1，就將全部的 pat1用 pat2 作替代

#    #將字串轉成array
#    string2array

#    #計算match的字數
#    expr string : pattern

#    str_find_expr - 用expr來搜尋字串
#    str_find_grep - 用grep來搜尋字串

#    str_toupper - 將字串換成大寫

#    isnum - 調查字串是否為整數

# Edit History: 
#   2010-12-08    File created.
#========================================================================
#========================================================================
#    str_special - 含控制文字的字串
#========================================================================

# 找出能夠顯示16進位的傾印清單(dump list)的指令
# (在Solaris裡面是od，在其它則是使用hexdump)
hexdump=`which hexdump 2>/dev/null`
if [ -x "$hexdump" ]; then
    DUMP="hexdump -C"
else
    DUMP="od -tx1"
fi


## 直接代入
str=':
	'            # 雖然眼睛看不到，這裡輸入的是「':<ENTER><TAB>'」。
echo "$str" | $DUMP  # 顯示字串的16進位傾印                                                                                                   


## 使用printf來代入
str=`printf ':\n\t'`
        # 「`...`」(指令替換)中因為最後的換行文字會被拿掉，所以
        # 「str=`printf ':\t\n'`」是無法成功的。
echo "$str" | $DUMP  # 顯示字串的16進位傾印

## 使用bash的「$'...'」來代入
str=$':\n\t'         # 這種表現方式只有在bash中才可以使用
echo "$str" | $DUMP  # 顯示字串的16進位傾印

#========================================================================
#    str_complex - 巢狀的字串("", ''的差異)
#========================================================================

testpath="process search"
#會視為一個字串
ls "process search"
ls "$testpath"
#視為兩個參數給ls
ls process search
ls $testpath

NAME="test"
#雙引號會套用值
TESTPATH="~/$NAME"
echo $TESTPATH
#單引號則不替換
TESTPATH='~/$NAME'
echo $TESTPATH

# do_manytimes
#   引數$1作為指令重複執行3次給矛的字串
do_manytimes() {
    for count in 1 2 3; do
    eval "$1"
    done
    echo
}

# 以各種的引數來呼叫do_manytimes
do_manytimes 'echo "Example A - $count"'     # [A] 這個OK
do_manytimes "echo \"Example B - $count\""   # [B] 這個可能不太好
do_manytimes "echo \"Example C - \$count\""  # [C] 這個OK


#引號的不同用法

# 顯示引數的數量以及一覽表
showargs() {
    echo "Number of args: $#"
    echo "List of args:"
    for arg in "$@"; do    # 對所有的引數做重複的動作
    echo "  $arg"
    done
}

# 在testvar中代入一個含有空白字元的字串
testvar="abc def ghi"

# 使用「"$testvar"」的情況
echo "*** Quoted by \"...\" ****"
showargs "$testvar"

# 使用「'$testvar'」的情況(變數不會被展開)
echo "*** Quoted by '...'  ***"
showargs '$testvar'

# 使用「$testvar」的情況(單字會被空白字元分割)
echo "*** Not quoted ***"
showargs $testvar

#========================================================================
#    str_compare - 比對字串
#========================================================================
# 比對用的字串
str1="foo"
str2=""

# 「[」指令會傳回與比較結果相應的終止碼
[ "$str1" = "foo" ];  echo $?
[ "$str1" != "foo" ]; echo $?

# 使用if敘述，進行相對應的處理
if [ "$str1" = "foo" ]; then
    echo '$str1 is foo'
else                                                                                                                                          
    echo '$str1 is not foo'
fi

# 也可以寫成這樣
[ -z "$str2" ] && echo '$str2 is empty' || echo '$str2 is not empty'

# 其它比較複雜的條件寫法
[ "$str1" = "foo" -a -z "$str2" ] && echo '$str1 is foo AND $str2 is empty'
[ "$str1" = "bar" -o -z "$str2" ] && echo '$str1 is bar OR $str2 is empty'

var0=abcd
if [ "$var0" == "abcd" ] ; then
	echo "equal"
fi


if [ $var0 = "abcd" ] ; then
	echo "equal"
fi

if [ $var0 = abcd ] ; then
	echo "equal"
fi

var1="mtu eth0"
if [[ "$var1" = "mtu "* ]] ; then
	echo "find mtu *"
fi

#Bash's [[ ]] doesn't get glob-expanded, unlike [ ] (which must, for historical reasons).
if [ "${var1:0:4}" == "mtu " ] ; then
	echo "find mtu[0:4]"
fi

#${var1:0:4} means the first four characters of $var1.
#Ah, sorry. Bash's POSIX emulation doesn't go far enough; a true original Bourne shell doesn't have ${var1:0:4}. You'll need something like mstrobl's solution.
if [ "$(echo "$var1" | cut -c1-4)" == "mtu " ] ; then
	echo "find | mut"
fi

#========================================================================
#    str_fieldsplit - 將字串分割成幾個單字
#========================================================================
# 對象字串
text="field1,field2,field3,field4,field5"

_IFS="$IFS"   # 先把IFS的內容存起來
IFS=','       # 將區隔文字設為「,」
set -- $text  # 分割:結果會被放到$1,...$9內
IFS="$_IFS"   # 將IFS的內容復原

# 顯示結果
echo "$2"
echo "$4"

#========================================================================
#    str_match_expr - 抽取出與正規表示一致的部分
#========================================================================
# 處理對象字串（HTML的一部分）
text="<a target=WINDOW href=URL>ANCHOR</a>"

# 將標籤或錨點的必要部分抽取出來
expr "$text" : '.* \(target=[^ >]*\)'
expr "$text" : '.* href=\([^ >]*\)'
expr "$text" : '.*>\(.*\)<'

#========================================================================
#    str_multiline - 寫一個橫跨多行的字串替換
#========================================================================
# 把「三隻小豬」裡面的小豬換成河馬，把母親換成父親
# (把一個包括換行字元的指令交給sed去處理)
cat <<'EOF' | sed 's/pigs/HIPPOPOTAMUSES/g
s/mother/FATHER/g'
Once upon a time there were three little pigs and the time came for 
them to leave home and seek their fortunes.
    Before they left, their mother told them "Whatever you do, do it 
the best that you can because that's the way to get along in the world.
EOF

#========================================================================
#========================================================================
#擷取字串,利用cut
echo $(echo "abcdef" | cut -c1-4)

# Shortest match from back of string(s)
gzfile=xxx.tar.gz
tarfile=${gzfile[@]%.gz}
echo $tarfile

#變數值替換
#如果 var 變數存在且為非空值，就傳回其值 ﹔如果 var 變數存在但為空值或者 var 變數根本不存在，則傳回 str。
var=
echo ${var:-str}
var=Iexists
echo ${var:-str}
unset var
echo ${var:-str}
#如果 var 變數存在且為非空值，就傳回其值 ﹔若 var 變數存在但為空值，則傳回空值 ﹔如果 var 變數不存在，則傳回 str。
var=
echo ${var-str}
var=Iexists
echo ${var-str}
unset var
echo ${var-str}

#如果 var 變數存在且為非空值，就傳回其值 ﹔如果 var 變數存在但為空值或者 var 變數根本不存在，就把 str 設定給 var ，並傳回 str。
var=test
echo ${var:=/etc/passwd}
#test
var=
echo ${var:=/etc/passwd}
#/etc/passwd
echo $var 
#/etc/passwd
unset var
echo ${var:=/etc/passwd}
#/etc/passwd
echo $var
#/etc/passwd

#如果 var 變數存在且為非空值，就傳回其值 ﹔若 var 變數存在但為空值，則傳回空值 ﹔如果 var 變數不存在，就把 str 設定給 var ，並傳回 str
var=test
echo ${var=/etc/passwd}
#test
var=
echo ${var=/etc/passwd}

unset var
echo ${var=/etc/passwd}
#/etc/passwd
echo $var 
#/etc/passwd 

#如果 var 變數存在且為非空值，就傳回其值 ﹔如果 var 變數存在但為空值或者 var 變數根本不存在，就會顯示 var: 及 info 的訊息。
var=test
echo ${var:?var is not exist}
#test
var=
#echo ${var:?null value}
#-bash: var: null value
unset var
#echo ${var:?var is not exist}
#-bash: var: var is not exist

#如果 var 變數存在且為非空值，就傳回其值 ﹔若 var 變數存在但為空值，則傳回空值 ﹔如果 var 變數不存在，就會顯示 var: 及 info 的訊息。
var=test
echo ${var?var is not exist}
#test
var=
echo ${var?null value} 

unset var
#echo ${var?var is not exist}
#-bash: var: var is not exist

#如果 var 變數存在且為非空值，則傳回 str ﹔如果 var 變數存在但為空值或者 var 變數根本不存在，就傳回空值。
var=test
echo ${var:+/etc/passwd}
#/etc/passwd
var=
echo ${var:+/etc/passwd}

unset var
echo ${var:+/etc/passwd}

#如果 var 變數存在，且不論為空值或非空值，皆傳回 str ﹔如果 var 變數不存在，就傳回空值。
var=test
echo ${var+/etc/passwd}
#/etc/passwd
var=
echo ${var+/etc/passwd}
#/etc/passwd 
unset var
echo ${var+/etc/passwd} 

#========================================================================
#    str_wordsplit - 取出字串的任意單字
#========================================================================
# 將變數text的內容分割為幾個單字，將各單字設定到 $1,$2 ... 當中
text='Your nature demands love and your happiness depends on it.'
set -- $text

# 顯示結果
echo "Number of words: $#"
echo "The fourth word: $4"

#========================================================================
#    str_substr_bash.sh - 取出字串的一部分（bash）
#========================================================================
# 取出「ABCDEFGHIJ」的第3個字到第7個字的內容
str="ABCDEFGHIJ"
start=3
end=7

# 在bash當中，是指定開始位置和要取出的長度                                                                                                    
# 「$(( 式字 ))」是bash的功能
offset=$(( start - 1 ))        # 開始位置（0=第1個字）
length=$(( end - start + 1 ))  # 要取出的長度

# 取出字串，並顯示結果
substr=${str:offset:length}
echo "$substr"
#========================================================================
#    str_substr.sh - 取出字串的一部分
#========================================================================
# 取出「ABCDEFGHIJ」的第三個字到第七個字
str="ABCDEFGHIJ"
start=3
end=7
substr=`echo "$str" | cut -c${start}-${end}`
echo "$substr"




#number 為一數字，若 var 的變數值含有 8 個字元，當 number 為 3 時，表示取得第三個字元以後的部分。
var=myshellscript
echo ${var:2}
#shellscript

#若 var 的變數值含有 8 個字元，當 n1 為 3，n2 為 6 時，表示取得第三個字元以後的六個字元。
var=myshellscript
echo ${var:2:5}
#shell

#========================================================================
#    str_length - 調查字串長度
#========================================================================
text="The quick brown fox jumps over the lazy dog."
echo "Length: ${#text}"


#傳回 var 變數值的字元數。
var=myshellscript
echo ${#var}
#13


#========================================================================
#    str_replace_bash - 取代字串（bash）
#========================================================================
# 取代用的字串
text="The quick brown fox jumps over the lazy fox."

# 將text中的「fox」取代為「DOG」
echo ${text/"fox"/"DOG"}   # 只取代第一個fox
echo ${text//"fox"/"DOG"}  # 取代所有的fox

# 使用萬用字元的例子:把「jumps」之後的內容改為「jumps...」
echo ${text/"jumps*"/"jumps..."}

#========================================================================
#    str_replace - 使用sed來取代字串
#========================================================================

# 取代用的字串
text="The quick brown fox jumps over the lazy fox."

# 將text中的「fox」取代為「DOG」
echo "$text" | sed 's/fox/DOG/'   # 只取代第一個出現的fox
echo "$text" | sed 's/fox/DOG/g'  # 將全部的fox取代掉

# 使用正規表示的例子:將「o」開頭的單字全部取代成「after」
echo "$text" | sed 's/\<o[^ ]*/after/'


#========================================================================
#========================================================================

#變數值樣式比對
#把 pattern 與 var 變數值做比對時，是從 var 變數值的前面部分比對起，如果有符合之處，就刪除變數值中最短的部分，並傳回其餘的變數值。
var=/home/barry/dir/file
echo ${var#/*/}
#barry/dir/file

#把 pattern 與 var 變數值做比對時，是從 var 變數值的前面部分比對起，如果有符合之處，就刪除變數值中最長的部分，並傳回其餘的變數值。
var=/home/barry/dir/file
echo ${var##/*/}
#file

#把 pattern 與 var 變數值做比對時，是從 var 變數值的後面部分比對起，如果有符合之處，就刪除變數值中最短的部分，並傳回其餘的變數值。
var=/home/barry/dir/
echo ${var%/*/}
#/home/barry

#把 pattern 與 var 變數值做比對時，是從 var 變數值的後面部分比對起，如果有符合之處，就刪除變數值中最長的部分，並傳回其餘的變數值。
var=/home/barry/test.tar.gz
echo ${var%%.*}
#/home/barry/test

#若變數值中含有 pat1，就將第一個 pat1用 pat2 作替代 。
var=/home/barry/barrydir/barryfile
echo ${var/barry/mary}
#/home/mary/barrydir/barryfile

#若變數值中含有 pat1，就將全部的 pat1用 pat2 作替代 。
var=/home/barry/barrydir/barryfile
echo ${var//barry/mary}
#/home/mary/marydir/maryfile

: ${LINES:=24} ${TERM:?"TERM not set"}
echo "$LINE $TERM"
#The : is a no-op, but the shell still evaluates its arguments. Thus LINES is set to 24 if LINES is empty or
#undefined. If TERM is empty or undefined, the whole script aborts with the error message "TERM not
#set".


#========================================================================
#    string2array
#========================================================================

#Method 1
#declare your array 
declare -a var 
foo="one,two,three,four"
#split your line using tr 
var=(`echo $foo | tr ',' ' '`) 

#print the whole array 
echo ${var[@]} 

#iterate over the array 
for s in ${var[@]}; do 
    echo $s 
done  

#Method 2, it works
foo="one,two,three,four"
OLD_IFS="$IFS"
IFS=","
bar=( $foo )
IFS="$OLD_IFS"

echo ${bar[0]}
echo ${bar[1]}
echo ${bar[2]}
echo ${bar[3]}


#========================================================================
#    string match number
#========================================================================
#計算有多少個pattern match的字數
ABC=abcdef
expr $ABC : '.*'
ABC=123abc
expr $ABC : '[0-9]*'

#match ()中的字串會被顯示出來 
expr abcdef : '.\([a-f]\{4\}\).'

#========================================================================
#    str_find_expr - 用expr來搜尋字串
#========================================================================
# 搜尋用的字串
text="The quick brown fox jumps over the lazy dog."

# 搜尋字串text中是否含有「fox」
if expr "$text" : '.*fox' >/dev/null; then
    echo "fox was found!"
else
    echo "not found"
fi


#========================================================================
#    str_find_grep - 用grep來搜尋字串
#========================================================================
# 搜尋用的字串
text="The quick brown fox jumps over the lazy dog."

# 搜尋text中是否含有「fox」字串
if echo "$text" | grep -q 'fox'; then
    echo "found"
else
    echo "not found"
fi                       

#========================================================================
#    str_toupper - 將字串換成大寫
#========================================================================
# 欲處理的字串
text="The quick brown fox jumps over the lazy dog."

# 將text中的小寫字換成大寫
result=`echo "$text" | tr 'a-z' 'A-Z'`
echo "$result"


#========================================================================
#    isnum - 調查字串是否為整數
#========================================================================
# is_num STR
#     調查STR是否為整數，並顯示訊息
is_num() {
    [ "$1" -eq 0 ] 2>/dev/null
    if [ $? -ge 2 ]; then
    echo "$1 is NOT a valid integer."
    else
    echo "$1 is a valid integer."
    fi  
}

# 呼叫is_num看看
is_num "256"
is_num "-32"
is_num "X64"

